/*
 * Copyright © 2022 plgxs.top All Rights Reserved Stranger.
 */

package top.plgxs.admin.utils.rsa;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

/**
 * 给子系统用
 *
 */
public class RSAUtil {
	
	public static final String X509 = "X.509";	// 
	
	/**
	 * 从后缀为.cer的文件获取公钥
	 * 客户端使用
	 * @param cerPath	后缀为.cer的文件所在路径
	 * @return
	 * @throws Exception
	 */
	private static PublicKey getPublicKey(String cerPath) throws Exception {
		X509Certificate cer = null;
		CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
		FileInputStream in = new FileInputStream(cerPath);
		cer = (X509Certificate) certificateFactory.generateCertificate(in);
		in.close();
		
//		System.out.println("读取Cer证书信息...");
//		System.out.println("x509Certificate_SerialNumber_序列号___:" + cer.getSerialNumber());
//		System.out.println("x509Certificate_getIssuerDN_发布方标识名___:" + cer.getIssuerDN());
//		System.out.println("x509Certificate_getSubjectDN_主体标识___:" + cer.getSubjectDN());
//		System.out.println("x509Certificate_getSigAlgOID_证书算法OID字符串___:" + cer.getSigAlgOID());
//		System.out.println("x509Certificate_getNotBefore_证书有效期___:" + cer.getNotAfter());
//		System.out.println("x509Certificate_getSigAlgName_签名算法___:" + cer.getSigAlgName());
//		System.out.println("x509Certificate_getVersion_版本号___:" + cer.getVersion());
//		System.out.println("x509Certificate_getPublicKey_公钥___:" + cer.getPublicKey());
		
		return cer.getPublicKey();
	}
	
	/**
	 * 经过BASE64加密过的公钥
	 * 客户端使用
	 * @param cerPath	后缀为.cer的文件所在路径
	 * @return			公钥（String类型）
	 * @throws Exception
	 */
	public static String getStrPublicKey(String cerPath) throws Exception {
		PublicKey publicKey = getPublicKey(cerPath);
		// BASE64加密
		String strPublicKey = CoderUtil.encryptBASE64(publicKey.getEncoded());
		return strPublicKey;
	}
	
	/**
	 * 公钥加密
	 * 客户端使用
	 * @param publicKey	公钥（String类型）
	 * @param data		需要加密的数据
	 * @return			rsa base64加密过的数据
	 * @throws Exception
	 */
	public static String encryptByPublicKey(String publicKey, String data) throws Exception {
		// BASE64解密
		byte[] pk = CoderUtil.decryptBASE64(publicKey);
		X509EncodedKeySpec spec = new X509EncodedKeySpec(pk);
		KeyFactory kf = KeyFactory.getInstance("RSA");
		// 获取公钥
		PublicKey pubKey = kf.generatePublic(spec);
		
		// 对数据加密
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, pubKey);
		
		byte[] doFinal = cipher.doFinal(data.getBytes());
		return CoderUtil.encryptBASE64(doFinal);
	}
	
	/**
	 * 公钥解密
	 * 客户端使用
	 * @param publicKey	公钥（String类型）
	 * @param data		需要解密的数据
	 * @return			String类型的数据
	 * @throws Exception
	 */
	public static String descryptByPublicKey(String publicKey, String data) throws Exception {
		// BASE64解密私钥
		byte[] pk = CoderUtil.decryptBASE64(publicKey);
		// BASE64解密数据
		byte[] text = CoderUtil.decryptBASE64(data);
		
		X509EncodedKeySpec spec = new X509EncodedKeySpec(pk);
		KeyFactory kf = KeyFactory.getInstance("RSA");
		// 获取公钥
		PublicKey pubKey = kf.generatePublic(spec);
		
		// 对数据解密
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, pubKey);
		
		byte[] doFinal = cipher.doFinal(text);
		return new String(doFinal);
	}

	/**
	 * 公钥解密 分段
	 * 客户端使用
	 * @param publicKey	公钥（String类型）
	 * @param data		需要解密的数据
	 * @return			String类型的数据
	 * @throws Exception
	 */
	public static String descryptByPublicKeyFen(String publicKey, String data) throws Exception {
		int MAX_DECRYPT_BLOCK = 64;
		try {
		      byte[] b = CoderUtil.decryptBASE64(data); 
		      int inputLen = b.length; 
		      ByteArrayOutputStream out = new ByteArrayOutputStream(); 
		      int offSet = 0; 
		      byte[] cache; 
		      int i = 0; 
		   // BASE64解密私钥
				byte[] pk = CoderUtil.decryptBASE64(publicKey);
				// BASE64解密数据
//				byte[] text = CoderUtil.decryptBASE64(data);
				
				X509EncodedKeySpec spec = new X509EncodedKeySpec(pk);
				KeyFactory kf = KeyFactory.getInstance("RSA");
				// 获取公钥
				PublicKey pubKey = kf.generatePublic(spec);
				
				// 对数据解密
				Cipher cipher = Cipher.getInstance("RSA");
				cipher.init(Cipher.DECRYPT_MODE, pubKey); 
		      // 对数据分段解密 
		      while (inputLen - offSet > 0) { 
		        if (inputLen - offSet > MAX_DECRYPT_BLOCK) { 
		          cache = cipher.doFinal(b, offSet, MAX_DECRYPT_BLOCK); 
		        } else { 
		          cache = cipher.doFinal(b, offSet, inputLen - offSet); 
		        } 
		        out.write(cache, 0, cache.length); 
		        i++; 
		        offSet = i * MAX_DECRYPT_BLOCK; 
		      } 
		      byte[] decryptedData = out.toByteArray(); 
		      out.close(); 
		      return new String(decryptedData); 
		    } catch (Exception e) {
//		logger.error(e.getMessage());
		}
		return null;
		
	}
	
}
